package com.alogic.blob;

import com.anysoft.util.*;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.w3c.dom.Element;
import java.io.InputStream;

/**
 * 可主从复制的BlobManager
 *
 * @since 1.6.13.18 [20200927 duanyy] <br>
 */
public class ReplicateBlobManager extends BlobManager.Abstract{

    /**
     * 主要的BlobManager
     */
    protected BlobManager master = null;

    /**
     * 备用BlobManager
     */
    protected BlobManager secondary = null;

    @Override
    public void configure(Element e, Properties p) {
        Properties props = new XmlElementProperties(e,p);

        Factory<BlobManager> f = new Factory<BlobManager>();
        Element elem = XmlTools.getFirstElementByPath(e,"master");
        if (elem != null){
            try {
                master = f.newInstance(elem, props, "module");
            }catch (Exception ex){
                LOG.error("Can not create blob manager with " + XmlTools.node2String(elem));
                LOG.error(ExceptionUtils.getStackTrace(ex));
            }
        }
        elem = XmlTools.getFirstElementByPath(e,"secondary");
        if (elem != null){
            try {
                secondary = f.newInstance(elem, props, "module");
            }catch (Exception ex){
                LOG.error("Can not create blob manager with " + XmlTools.node2String(elem));
                LOG.error(ExceptionUtils.getStackTrace(ex));
            }
        }
        configure(props);
    }

    @Override
    public BlobWriter newFile(String id) {
        return master != null ? new RelicateBlobWrite(master.newFile(id),secondary != null?secondary.newFile(id):null): null;
    }

    @Override
    public BlobWriter newFile(String id,Properties ctx) {
        return master != null ? new RelicateBlobWrite(master.newFile(id,ctx),secondary != null?secondary.newFile(id,ctx):null): null;
    }

    @Override
    public BlobReader getFile(String id) {
        return master == null ? null : master.getFile(id);
    }

    @Override
    public boolean existFile(String id) {
        return master == null ? null : master.existFile(id);
    }

    @Override
    public boolean deleteFile(String id) {
        if (secondary != null){
            secondary.deleteFile(id);
        }
        return master != null ? master.deleteFile(id):false;
    }

    public static class RelicateBlobWrite implements BlobWriter{
        protected BlobWriter master;
        protected BlobWriter secondary;
        protected RelicateBlobWrite(BlobWriter master,BlobWriter secondary){
            this.master = master;
            this.secondary = secondary;
        }

        @Override
        public void write(InputStream in, long contentLength, boolean toCloseStreamWhenFinished) {
            if (master != null){
                master.write(in,contentLength,toCloseStreamWhenFinished);
            }
            if (secondary != null){
                try {
                    in.reset();
                    secondary.write(in, contentLength, toCloseStreamWhenFinished);
                }catch (Exception ex){
                    LOG.error("IO Exception:" + ex.getMessage());
                    LOG.error(ExceptionUtils.getStackTrace(ex));
                }
            }
        }

        @Override
        public void write(byte[] content) {
            if (master != null){
                master.write(content);
            }
            if (secondary != null){
                secondary.write(content);
            }
        }

        @Override
        public BlobInfo getBlobInfo() {
            return master != null ? master.getBlobInfo():null;
        }
    }
}